home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ip / ka9q / osrc.arc / AX25SUBR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-19  |  10.0 KB  |  442 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "ax25.h"
  5. #include "lapb.h"
  6. #include <ctype.h>
  7.  
  8. void recover(),send_ack(),pollthem(),ax_incom();
  9. char *putaxaddr(),*getaxaddr();
  10.  
  11. struct ax25_cb *Ax25_cb[NHASH];
  12.  
  13. /* Default AX.25 parameters */
  14. int16 T3init = 0 / MSPTICK;    /* No keep-alive polling */
  15. int16 Maxframe = 1;        /* Stop and wait */
  16. int16 N2 = 10;            /* 10 retries */
  17. int16 Axwindow = 2048;        /* 2K incoming text before RNR'ing */
  18. int16 Paclen = 256;        /* 256-byte I fields */
  19. int16 Pthresh = 128;        /* Send polls for packets larger than this */
  20. int32 Axirtt = 5000/MSPTICK;    /* Initial round trip estimate */
  21. int Axversion = V1;        /* Protocol version */
  22.  
  23. /* Address hash function. Exclusive-ORs each byte, ignoring
  24.  * such insignificant, annoying things as E and H bits
  25.  */
  26. int16
  27. ax25hash(s)
  28. struct ax25_addr *s;
  29. {
  30.     register unsigned x;
  31.     register int i;
  32.     register char *cp;
  33.  
  34.     x = 0;
  35.     cp = s->call;
  36.     for(i=ALEN; i!=0; i--)
  37.         x ^= *cp++;
  38.     x &= 0xfe;
  39.     x ^= s->ssid & SSID;
  40.     return uchar(x) % NHASH;
  41. }
  42. /* Look up entry in hash table */
  43. struct ax25_cb *
  44. find_ax25(addr)
  45. register struct ax25_addr *addr;
  46. {
  47.     int16 hashval;
  48.     register struct ax25_cb *axp;
  49.  
  50.     /* Find appropriate hash chain */
  51.     hashval = ax25hash(addr);
  52.  
  53.     /* Search hash chain */
  54.     for(axp = Ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  55.         if(addreq(&axp->remote,addr)){
  56.             return axp;
  57.         }
  58.     }
  59.     return NULLAX25;
  60. }
  61.  
  62. /* Remove address entry from hash table */
  63. del_ax25(axp)
  64. register struct ax25_cb *axp;
  65. {
  66.     int16 hashval;
  67.  
  68.     if(axp == NULLAX25)
  69.         return;
  70.     /* Remove from hash header list if first on chain */
  71.     hashval = ax25hash(&axp->remote);
  72.  
  73.     /* Remove from chain list */
  74.     if(axp->prev == NULLAX25)
  75.         Ax25_cb[hashval] = axp->next;
  76.     else
  77.         axp->prev->next = axp->next;
  78.     if(axp->next != NULLAX25)
  79.         axp->next->prev = axp->prev;
  80.  
  81.     /* Timers should already be stopped, but just in case... */
  82.     stop_timer(&axp->t1);
  83.     stop_timer(&axp->t3);
  84.  
  85.     /* Free allocated resources */
  86.     free_q(&axp->txq);
  87.     free_q(&axp->rxasm);
  88.     free_q(&axp->rxq);
  89.     free((char *)axp);
  90. }
  91.  
  92. /* Create an ax25 control block. Allocate a new structure, if necessary,
  93.  * and fill it with all the defaults. The caller
  94.  * is still responsible for filling in the reply address
  95.  */
  96. struct ax25_cb *
  97. cr_ax25(addr)
  98. struct ax25_addr *addr;
  99. {
  100.     register struct ax25_cb *axp;
  101.     int16 hashval;
  102.  
  103.     if(addr == NULLAXADDR)
  104.         return NULLAX25;
  105.  
  106.     if((axp = find_ax25(addr)) == NULLAX25){
  107.         /* Not already in table; create an entry
  108.          * and insert it at the head of the chain
  109.          */
  110.         /* Find appropriate hash chain */
  111.         hashval = ax25hash(addr);
  112.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  113.         if(axp == NULLAX25)
  114.             return NULLAX25;
  115.         /* Insert at beginning of chain */
  116.         axp->next = Ax25_cb[hashval];
  117.         if(axp->next != NULLAX25)
  118.             axp->next->prev = axp;
  119.         Ax25_cb[hashval] = axp;
  120.     }
  121.     axp->user = -1;
  122.     axp->maxframe = Maxframe;
  123.     axp->window = Axwindow;
  124.     axp->paclen = Paclen;
  125.     axp->proto = Axversion;    /* Default, can be changed by other end */
  126.     axp->pthresh = Pthresh;
  127.     axp->n2 = N2;
  128.     axp->srt = Axirtt;
  129.     axp->t1.start = 2*axp->srt;
  130.     axp->t1.func = recover;
  131.     axp->t1.arg = (char *)axp;
  132.  
  133.     axp->t3.start = T3init;
  134.     axp->t3.func = pollthem;
  135.     axp->t3.arg = (char *)axp;
  136.  
  137.     return axp;
  138. }
  139.  
  140. /*
  141.  * setcall - convert callsign plus substation ID of the form
  142.  * "KA9Q-0" to AX.25 (shifted) address format
  143.  *   Address extension bit is left clear
  144.  *   Return -1 on error, 0 if OK
  145.  */
  146. int
  147. setcall(out,call)
  148. struct ax25_addr *out;
  149. char *call;
  150. {
  151.     int csize;
  152.     unsigned ssid;
  153.     register int i;
  154.     register char *cp,*dp;
  155.     char c;
  156.  
  157.     if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  158.         return -1;
  159.     }
  160.     /* Find dash, if any, separating callsign from ssid
  161.      * Then compute length of callsign field and make sure
  162.      * it isn't excessive
  163.      */
  164.     dp = strchr(call,'-');
  165.     if(dp == NULLCHAR)
  166.         csize = strlen(call);
  167.     else
  168.         csize = dp - call;
  169.     if(csize > ALEN)
  170.         return -1;
  171.     /* Now find and convert ssid, if any */
  172.     if(dp != NULLCHAR){
  173.         dp++;    /* skip dash */
  174.         ssid = atoi(dp);
  175.         if(ssid > 15)
  176.             return -1;
  177.     } else
  178.         ssid = 0;
  179.     /* Copy upper-case callsign, left shifted one bit */
  180.     cp = out->call;
  181.     for(i=0;i<csize;i++){
  182.         c = *call++;
  183.         if(islower(c))
  184.             c = toupper(c);
  185.         *cp++ = c << 1;
  186.     }
  187.     /* Pad with shifted spaces if necessary */
  188.     for(;i<ALEN;i++)
  189.         *cp++ = ' ' << 1;
  190.     
  191.     /* Insert substation ID field and set reserved bits */
  192.     out->ssid = 0x60 | (ssid << 1);
  193.     return 0;
  194. }
  195. /* Set a digipeater string in an ARP table entry */
  196. setpath(out,in,cnt)
  197. char *out;    /* Target char array containing addresses in net form */
  198. char *in[];    /* Input array of tokenized callsigns in ASCII */
  199. int cnt;    /* Number of callsigns in array */
  200. {
  201.     struct ax25_addr addr;
  202.  
  203.     if(cnt == 0)
  204.         return;
  205.     while(cnt-- != 0){
  206.         setcall(&addr,*in++);
  207.         addr.ssid &= ~E;
  208.         out = putaxaddr(out,&addr);
  209.     }
  210.     out[-1] |= E;
  211. }
  212. addreq(a,b)
  213. register struct ax25_addr *a,*b;
  214. {
  215.     if(memcmp(a->call,b->call,ALEN) != 0)
  216.         return 0;
  217.     if((a->ssid & SSID) != (b->ssid & SSID))
  218.         return 0;
  219.     return 1;
  220. }
  221. /* Convert encoded AX.25 address to printable string */
  222. pax25(e,addr)
  223. char *e;
  224. struct ax25_addr *addr;
  225. {
  226.     register int i;
  227.     char c,*cp;
  228.  
  229.     cp = addr->call;
  230.     for(i=ALEN;i != 0;i--){
  231.         c = (*cp++ >> 1) & 0x7f;
  232.         if(c == ' ')
  233.             break;
  234.         *e++ = c;
  235.     }
  236.     if ((addr->ssid & SSID) != 0)
  237.         sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);    /* ssid */
  238.     else
  239.         *e = 0;
  240. }
  241. /* Print a string of AX.25 addresses in the form
  242.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  243.  * Designed for use by ARP - arg is a char string
  244.  */
  245. psax25(e,addr)
  246. register char *e;
  247. register char *addr;
  248. {
  249.     int i;
  250.     struct ax25_addr axaddr;
  251.     char tmp[16];
  252.  
  253.     e[0] = '\0';    /* Give strcat a staritng point */
  254.     for(i=0;;i++){
  255.         /* Create local copy in host-format structure */
  256.         addr = getaxaddr(&axaddr,addr);
  257.  
  258.         /* Create ASCII representation and append to output */
  259.         pax25(tmp,&axaddr);
  260.         strcat(e,tmp);
  261.  
  262.         if(axaddr.ssid & E)
  263.             break;
  264.         if(i == 0)
  265.             strcat(e," via ");
  266.         else
  267.             strcat(e,",");
  268.         /* Not really necessary, but speeds up subsequent strcats */
  269.         e += strlen(e);
  270.     }
  271. }
  272. char *
  273. getaxaddr(ap,cp)
  274. register struct ax25_addr *ap;
  275. register char *cp;
  276. {
  277.     memcpy(ap->call,cp,ALEN);
  278.     cp += ALEN;
  279.     ap->ssid = *cp++;
  280.     return cp;
  281. }
  282. char *
  283. putaxaddr(cp,ap)
  284. register char *cp;
  285. register struct ax25_addr *ap;
  286. {
  287.     memcpy(cp,ap->call,ALEN);
  288.     cp += ALEN;
  289.     *cp++ = ap->ssid;
  290.     return cp;
  291. }
  292.  
  293. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  294. struct mbuf *
  295. htonax25(hdr,data)
  296. register struct ax25 *hdr;
  297. struct mbuf *data;
  298. {
  299.     struct mbuf *bp;
  300.     register char *cp;
  301.     register int16 i;
  302.  
  303.     if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  304.         return NULLBUF;
  305.  
  306.     /* Allocate space for return buffer */
  307.     i = AXALEN * (2 + hdr->ndigis);
  308.     if((bp = pushdown(data,i)) == NULLBUF)
  309.         return NULLBUF;
  310.  
  311.     /* Now convert */
  312.     cp = bp->data;
  313.  
  314.     hdr->dest.ssid &= ~E;    /* Dest E-bit is always off */
  315.     /* Encode command/response in C bits */
  316.     switch(hdr->cmdrsp){
  317.     case COMMAND:
  318.         hdr->dest.ssid |= C;
  319.         hdr->source.ssid &= ~C;
  320.         break;
  321.     case RESPONSE:
  322.         hdr->dest.ssid &= ~C;
  323.         hdr->source.ssid |= C;
  324.         break;
  325.     default:
  326.         hdr->dest.ssid &= ~C;
  327.         hdr->source.ssid &= ~C;
  328.         break;
  329.     }
  330.     cp = putaxaddr(cp,&hdr->dest);
  331.  
  332.     /* Set E bit on source address if no digis */
  333.     if(hdr->ndigis == 0){
  334.         hdr->source.ssid |= E;
  335.         putaxaddr(cp,&hdr->source);
  336.         return bp;
  337.     }
  338.     hdr->source.ssid &= ~E;
  339.     cp = putaxaddr(cp,&hdr->source);
  340.  
  341.     /* All but last digi get copied with E bit off */
  342.     for(i=0; i < hdr->ndigis - 1; i++){
  343.         hdr->digis[i].ssid &= ~E;
  344.         cp = putaxaddr(cp,&hdr->digis[i]);
  345.     }
  346.     hdr->digis[i].ssid |= E;
  347.     cp = putaxaddr(cp,&hdr->digis[i]);
  348.     return bp;
  349. }
  350. /* Convert an AX.25 ARP table entry into a host format address structure
  351.  * ready for use in transmitting a packet
  352.  */
  353. int
  354. atohax25(hdr,hwaddr,source)
  355. register struct ax25 *hdr;
  356. register char *hwaddr;
  357. struct ax25_addr *source;
  358. {
  359.     register struct ax25_addr *axp;
  360.  
  361.     hwaddr = getaxaddr(&hdr->dest,hwaddr);    /* Destination address */
  362.     ASSIGN(hdr->source,*source);        /* Source address */
  363.     if(hdr->dest.ssid & E){
  364.         /* No digipeaters */
  365.         hdr->ndigis = 0;
  366.         hdr->dest.ssid &= ~E;
  367.         hdr->source.ssid |= E;
  368.         return 2;
  369.     }
  370.     hdr->source.ssid &= ~E;
  371.     hdr->dest.ssid &= ~E;
  372.     for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  373.         hwaddr = getaxaddr(axp,hwaddr);
  374.         if(axp->ssid & E){
  375.             hdr->ndigis = axp - hdr->digis + 1;
  376.             return hdr->ndigis;
  377.         }
  378.     }
  379.     return -1;
  380. }
  381. /* Convert a network-format AX.25 header into a host format structure
  382.  * Return -1 if error, number of addresses if OK
  383.  */
  384. int
  385. ntohax25(hdr,bpp)
  386. register struct ax25 *hdr;    /* Output structure */
  387. struct mbuf **bpp;
  388. {
  389.     register struct ax25_addr *axp;
  390.     char buf[AXALEN];
  391.  
  392.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  393.         return -1;
  394.     getaxaddr(&hdr->dest,buf);
  395.  
  396.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  397.         return -1;
  398.     getaxaddr(&hdr->source,buf);
  399.  
  400.     /* Process C bits to get command/response indication */
  401.     if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  402.         hdr->cmdrsp = UNKNOWN;
  403.     else if(hdr->source.ssid & C)
  404.         hdr->cmdrsp = RESPONSE;
  405.     else
  406.         hdr->cmdrsp = COMMAND;
  407.  
  408.     hdr->ndigis = 0;
  409.     if(hdr->source.ssid & E)
  410.         return 2;    /* No digis */
  411.  
  412.     /* Process the digipeaters */
  413.     for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  414.         if(pullup(bpp,buf,AXALEN) < AXALEN){
  415.             return -1;
  416.         }
  417.         getaxaddr(axp,buf);
  418.         if(axp->ssid & E){    /* Last one */
  419.             hdr->ndigis = axp - hdr->digis + 1;
  420.             return hdr->ndigis + 2;            
  421.         }
  422.     }
  423.     return -1;    /* Too many digis */
  424. }
  425.  
  426. /* Figure out the frame type from the control field
  427.  * This is done by masking out any sequence numbers and the
  428.  * poll/final bit after determining the general class (I/S/U) of the frame
  429.  */
  430. int16
  431. ftype(control)
  432. register char control;
  433. {
  434.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  435.         return I;
  436.     if(control & 2)        /* U-frames use all except P/F bit for type */
  437.         return(control & ~PF);
  438.     else            /* S-frames use low order 4 bits for type */
  439.         return(control & 0xf);
  440. }
  441.  
  442.